#include "UsbInStream.h"
#include "VideoDecode.h"
#include "AudioInMgr.h"
#include "UsbAVStream.h"
#include "UacUtil.h"
#include "AudioEncode.h"
#include <thread>
#include "CurtainActManager.h"
#include "StreamerCurtainPlay.h"


extern "C" unsigned long long vdo_get_time();

namespace Media{

using namespace std;

#if 1
const uint8_t formatSize = 3;
const string formatStr[formatSize] = {"H.264", "H.264", "Motion-JPEG"};
const int widthArray[formatSize]  = {1920, 1280, 1280}; //1920
const int heightArray[formatSize] = {1080, 720, 720}; //1080

#else
const string formatStr[2] = {"Motion-JPEG", "H.264"};
const int widthArray[2]  = {1280, 1280};
const int heightArray[2] = {720, 720};
#endif

static const string audioRates[5] = {"48000", "32000", "16000", "8000"};


std::map<std::string, UsbInStream *>    UsbInStream::sm_streamMap;
std::recursive_mutex 		            UsbInStream::sm_mapMutex;


UsbInStream *UsbInStream::instance(std::string channel)
{
    std::lock_guard<std::recursive_mutex> guard(sm_mapMutex);
    
	if(sm_streamMap.find(channel) == sm_streamMap.end())
	{
		sm_streamMap[channel] = new UsbInStream(channel);
	}

	return sm_streamMap[channel];
}

UsbInStream::UsbInStream(std::string channel) 
{  
    m_taskTimer.reset();

    m_usbStreamCtl = UsbAVStream::instance();

    if(m_usbStreamCtl)
    m_usbStreamCtl->addHotplugCb(channel, [this](string usbport, bool status){return usbStatusCallback(usbport, status);});  //usb插拔回调

}

bool UsbInStream::SaveToCommQueue(FramePtr& msg, uint8_t index)
{
    if (msg.get() == NULL || index >= QueueArray)
    {
        return false;
    }

    if (m_frameaQueue[index].size() >= QueueSize)
    {

        // if (index == 0)
        //     LOG_PrintInfo("saveToCommQueue::enter [%s] [%d] qindex=%d,size=%d\n", __FILE__, __LINE__, index, m_frameaQueue[index].size());

        m_queueMutex[index].lock();
        m_frameaQueue[index].front();//处理队列中消息,移除最早的数据	
        m_frameaQueue[index].pop();
        m_queueMutex[index].unlock();

    }

    //存队列
    m_queueMutex[index].lock();
    m_frameaQueue[index].push(msg);
    m_queueMutex[index].unlock();

    return true;
}

bool UsbInStream::GetCommQueueMsg(FramePtr& msg, uint8_t index)
{
    if (index >= QueueArray)
    {
        return false;
    }

    m_queueMutex[index].lock();
    if (!m_frameaQueue[index].empty())
    {
        msg = m_frameaQueue[index].front();//处理队列中消息		
        m_frameaQueue[index].pop();

        //printf("enter [%s] [%d] \n",__FILE__,__LINE__);
        m_queueMutex[index].unlock();
        return true;
    }
    m_queueMutex[index].unlock();
    return false;
}

bool UsbInStream::directGetVideoData(SCREEN_vencPacket_t * packet)
{   
    static uint64_t lastTime = 0;
    static const uint8_t sendFrq = 30;

    if (GetCommQueueMsg(m_framePtr, 1))
    {
        packet->dataLen = m_framePtr->size;
        packet->pBuf = m_framePtr->data;
        packet->pts = m_framePtr->timestamp;
        //LOG_PrintWarn("m_framePtr->size=%d\n",m_framePtr->size);

        uint64_t runtime = vdo_get_time() - lastTime;
        if (runtime < sendFrq)
        {
            usleep((sendFrq - runtime) * 1000);
        }

        lastTime = vdo_get_time();

        return true;
    }

    return false;
}

bool UsbInStream::clearVideoQueue(uint8_t index)
{
    if (index >= QueueArray)
    {
        return false;
    }

    m_queueMutex[index].lock();
    while (!m_frameaQueue[index].empty()) m_frameaQueue[index].pop();
    m_queueMutex[index].unlock();

    return true;
}

void UsbInStream::StreamInProc(Fdt::Thread *thread)
{
    thread->setPriority(Fdt::PRIORITY_NORMAL, Fdt::POLICY_RR); 

#if 1
    FramePtr framePtr;
    uint64_t time1 = vdo_get_time();
    const uint8_t sendFrq = 30;
    const uint16_t maxFreq = 1000;

    while(thread->running())
    {
        if (!GetCommQueueMsg(framePtr, 0))
        {
            thread->sleep(3);
            continue;
        }

        sendVideoPacket(framePtr->data, framePtr->size, framePtr->timestamp);

        //media_FILE_Write("/tmp/usbin.h264", framePtr->data, framePtr->size);

        uint64_t runtime = vdo_get_time() - time1;
        if (runtime < sendFrq)
        {
            thread->sleep(sendFrq - runtime);
        }

        time1 = vdo_get_time();
    }
#endif
    
}

bool UsbInStream::usbStatusCallback(string usbport, bool status)
{
    LOG_PrintInfo("usbStatusCallback::usbport=%s, status:%d\n", usbport.c_str(), status);

    bool isUpdate = false;
    int playNum = 0;
    bool switchFlg = false;
    CurtainActManager::instance()->isPlayDefCurtain(switchFlg, playNum);
    if(switchFlg)
    {
        std::map<std::string, std::string> posInfo;
        
        UsbAVStream::instance()->getUsbStreamPos(posInfo, isUpdate);
    }

    int ability = 0;
    UsbAVStream::instance()->getAbility(usbport, ability);

    ///usb音视频获取位置调整后重启场景
    if((switchFlg && isUpdate)
      || ((playNum == DymicMirrorNum || playNum == StreamerNum) 
        && ((!status && (m_usbInAbility & UACOUT) == UACOUT))
          || (status && (ability & UACOUT) == UACOUT)))
    {
        Json::Value root = Json::Value::null;
        root["Number"] = playNum;
        root["PlayMode"] = 0;
        root["Action"] = 1;

        auto lam = [this, root, playNum]()
        {
            if(playNum == StreamerNum)
            {
                return StreamerCurtainPlay::instance()->playStreamerCurtain(LOCAL_STREAMER);
            }
            
            if(playNum == DymicMirrorNum)
            {
                if(!CurtainActManager::instance()->dymicSwitchTable(false))
                {
                    errorf("dymicSwitchTable failed\n");
                    return false;
                }
            }
            return CurtainActManager::instance()->setPlayStrategy(root); 
        };
        thread strategyThread(lam);
        strategyThread.detach(); 

        return true;
    }

    ///正常热插拔处理
    bool uacoutFlg = false;
    if((m_usbName == usbport) && m_playFlg)
    {
        if(status)
        {
            start(m_curPlayInfo);
        }
        else
        {
            stop(false);
        }
    }   
    if((m_usbOutPort == usbport) && m_outEnable)
    {
        if(status)
        {
            Json::Value params = m_uacOutParams;
            
            outputStart(m_outType, m_usbOutPort);

            if(params != Json::nullValue
              && m_uacOutParams != params)
            {
                CurtainActManager::instance()->uacoutChangeDeal(playNum);
            }
        }
        else
        {
            outputStop(m_outType, m_usbOutPort, false);
        }
    }

    return true;
}

bool UsbInStream::start(StreamPlayInfo playInfo)
{	
    LOG_PrintWarn("type=%d, streamInfo=%s, playAbility=%d, audioChn=%d, videoChn=%d\n",
                playInfo.stream.type,playInfo.stream.content, playInfo.playAbility, playInfo.audioChn, playInfo.videoChn);

    if(!m_started)
    { 
        m_started = true;

        m_playFlg = true;

        m_curPlayInfo = playInfo;
        
        m_playAbility = playInfo.playAbility;
        
        ///创建视频解码
        if((m_playAbility == VIDEO_AUDIO) || (m_playAbility == VIDEO_ONLY))
        {
            if(m_videoChannel != playInfo.videoChn)
            {            
                m_videoChannel = playInfo.videoChn;
                m_pVideoDecode = VideoDecode::instance(m_videoChannel); 
            }
            if(!m_pVideoDecode)
            {
                errorf("m_videoDecoder is NULL \n");
                return false;
            }

            clearVideoQueue(0);
            clearVideoQueue(1);
        }

        ///创建音频输入管理对象
        if((m_playAbility == VIDEO_AUDIO) || (m_playAbility == AUDIO_ONLY))
        {
            if(m_audioChannel != playInfo.audioChn)
            {            
                m_audioChannel = playInfo.audioChn;
                m_pAudioInput = AudioInMgr::instance(m_audioChannel); 

                if(!m_pAudioInput)
                {
                    return false;
                }

                AudioInDesc inDesc = {0};
                inDesc.card = 0;
                inDesc.channel = m_audioChannel;
                if(!m_pAudioInput->createAudioIn(inDesc))
                {
                    return false;
                }
            } 
        }

        m_streamInfo = playInfo.stream;
        m_usbName = playInfo.stream.content;

        if(!m_usbStreamCtl)
        {
            return false;
        }       
        
    	///获取USB对象能力
    	m_usbStreamCtl->getAbility(m_usbName, m_usbInAbility);
    	if(m_usbInAbility == 0)
    	{
            LOG_PrintError("USBIN:%s, m_usbInAbility is 0 \n", m_usbName.c_str());

            m_started = false;
            
            return false;
    	}

    	LOG_PrintInfo("USBIN=%s, m_usbInAbility:%d\n", m_usbName.c_str(), m_usbInAbility);
    	
        ///按任务启动流
        m_taskInfo = playInfo.task;
    	//m_taskTimer.reset(new Fdt::Timer(m_taskInfo.StartTime * 1000, ([this](){return this->streamStart();}), nullptr));


    	streamStart();

    	m_dropFrame = true;
    	   	
    }
  
	return true;
}

bool UsbInStream::stop(bool flag)
{
    LOG_PrintWarn("stop enter \n");
	if(m_started || m_playFlg)
    {
        m_started = false;

        //falg为false代表本地热插拔暂时停止，为true代表远端控制停止
        if(flag)
        {
            m_playFlg = false;
            memset(&m_curPlayInfo, 0, sizeof(m_curPlayInfo));

            LOG_PrintWarn("stop enter1 \n");
            
            streamStop();

            m_streamInThread.stop();

            LOG_PrintWarn("stop enter2 \n");
        }

        if((m_playAbility == VIDEO_AUDIO) || (m_playAbility == VIDEO_ONLY))
        {
        	if (!m_pVideoDecode || !m_pVideoDecode->stop())
        	{
        		return false;
        	}
    	} 

    	//m_usbInFormat="";
    	m_usbInAbility = 0;

        clearVideoQueue(0);
        clearVideoQueue(1);

    	//LOG_PrintWarn("stop enter3 \n");
    }
    LOG_PrintWarn("stop leave \n");

	return true;
}

bool UsbInStream::onVideoFrame(void *buffer, int length)
{
    uint64_t timestamp = vdo_get_time();    
    // tracef(" UsbInStream  onVideoFrame   %llu", timestamp);

    if(m_usbInFormat == "H.264")
    {
        ///过滤起始的P帧
        char *data = (char *)buffer;
        if(m_dropFrame && length > 4)
        {
            int frameType = data[4] & 0x1F;          
            if(0x07 == frameType )
            {
                m_dropFrame = false;
                LOG_PrintWarn("UsbInStream:: dropFrame done...\n");
            }
            else
            {
                return true;
            } 
        }
    }
    else if(m_usbInFormat == "H.265")
    {       
        char *data = (char *)buffer;
        if(m_dropFrame && length > 4)
        {
            int frameType =  H265_TYPE(data[4]);   
            if(0x20 == frameType )
            {
                m_dropFrame = false;
                LOG_PrintWarn("UsbInStream:: dropFrame done...\n");
            }
            else
            {
                return true;
            } 
        }
    }
    
    uint8_t dealFlg = CurtainActManager::instance()->getUsbVideoInParam();

    FramePtr videoFrame(new FrameBuffer(length));
    videoFrame->timestamp = timestamp; //vdo_get_time();
    videoFrame->size = length;

    memcpy(videoFrame->data, buffer, length);

    if (((dealFlg & 0x01) == 0x01)) //byom输出
    {
        if(m_usbInFormat == "H.264" || m_usbInFormat == "H.265")
        {
            SaveToCommQueue(videoFrame, 1);
        }
        else
        {
            SaveToCommQueue(videoFrame, 0);
            return true;
        }
    }

    if ((dealFlg >> 1) != 0)//其他输出
    {
        SaveToCommQueue(videoFrame, 0);
    }

    return true;
}

bool UsbInStream::onAudioFrame(void *buffer, int length)
{
    uint64_t timestamp = vdo_get_time();    
    // tracef(" UsbInStream  onAudioFrame   %llu", timestamp);
    sendAudioPacket((unsigned char *)buffer, length, timestamp);
	return true;
}

bool UsbInStream::streamStart()
{
    bool result = false;
    if(m_usbStreamCtl)
    {
        int ability = (m_usbInAbility& 0xff);
        Json::Value videoParams = Json::Value::null;
        Json::Value audioParams = Json::Value::null;
    	switch(ability)
    	{
            case 0x01:
            {               
            	m_usbStreamCtl->getSupportParams(m_usbName, UVCIN, videoParams);
            	LOG_PrintInfo("UVCIN:%d ---> %s", UVCIN,  videoParams.toStyledString().c_str());
                break;
            }
            case 0x02:
            case 0x06:
            {
                getUsbAudioParams(m_usbName, UACIN, audioParams);
                break;
            }
            case 0x03:
            case 0x07:
            { 
                m_usbStreamCtl->getSupportParams(m_usbName, UVCIN, videoParams);
            	LOG_PrintInfo("UVCIN:%d ---> %s", UVCIN,  videoParams.toStyledString().c_str());

            	getUsbAudioParams(m_usbName, UACIN, audioParams);
                break;
            }
            default:
                break;
    	}

        if(videoParams.isMember("Formats")
          && ((m_playAbility == VIDEO_AUDIO) || (m_playAbility == VIDEO_ONLY)))
        {
        	uint arraySize = videoParams["Formats"].size();
        	Json::Value params = Json::Value::null;
        	Json::Value paramSet = Json::Value::null;
        	bool dealFlg = false;
        	uint i = 0;
        	
        	VideoDecFormat decFormat;
            memset(&decFormat, 0, sizeof(VideoDecFormat));

            string format;
            for(uint8_t j = 0; j < formatSize; ++j)
            {
                format = formatStr[j];
                
            	for(i = 0; i < arraySize; ++i)
            	{
                    params =  videoParams["Formats"][i];
                    if(!params.isMember("format") 
                      || !params.isMember("height")
                      || !params.isMember("width"))
                    {
                        continue;
                    }

                    if((params["format"].asString() == format)
                      && (params["height"].asInt() == heightArray[j]) //VI_HEIGHT
                      && (params["width"].asInt() == widthArray[j])) //VI_WIDTH
                    {
                        break;
                    } 
            	}  
            	if(i != arraySize)
            	{
                    dealFlg = true;
                    paramSet = videoParams["Formats"][i];
                    
                    if(format == "H.264")
                    {
                        decFormat.type = videoEncH264;                        
                    }
                    else if(format == "Motion-JPEG")
                    {
                        decFormat.type = videoEncMotionJPEG;
                    }

                    break;
            	}
        	}
        	
        	if(dealFlg)
        	{   

                LOG_PrintInfo("UVCIN dealFlg:%d,format:%s,m_usbInFormat:%s\n", dealFlg, format.c_str(), m_usbInFormat.c_str());

                if (m_usbInFormat != format)
                {
                    //设置编码格式
                    if (!m_pVideoDecode->setFormat(&decFormat))
                    {
                        errorf("m_pVideoDecode setFormat failed\n");
                        return false;
                    }

                    m_usbInFormat = format;
                    tracef("m_pVideoDecode setFormat success\n");
                }

                //启动编码   
                if(!m_pVideoDecode->start())
                {
                    errorf("m_pVideoDecode start failed\n");
                    return false;
                }

                LOG_PrintInfo("UVCINset:%d ---> %s", UVCIN,  paramSet.toStyledString().c_str());
            	result = m_usbStreamCtl->setParams(m_usbName, UVCIN, paramSet);
            	if(!result)
            	{
                    errorf("m_usbName:%s m_usbStreamCtl->setParams UVCIN failed\n",m_usbName.c_str());
                    return false;
            	}

            	m_streamInThread.start([this](Fdt::Thread *thread){this->StreamInProc(thread);}); //启动单独线程处理流

                if(CurtainActManager::instance()->isUsbVideoCapture())
                {
                    result = m_usbStreamCtl->startStream(m_usbName, UVCIN, [this](void *buffer, int length){return onVideoFrame(buffer, length);});
                    if(!result)
                	{
                        errorf("m_usbName:%s m_usbStreamCtl->setParams UVCIN failed\n", m_usbName.c_str());
                        return false;
                	}
                    m_dynamicStartVideo.store(false);
                	LOG_PrintInfo("m_usbName:%s UVCIN startStream success\n",m_usbName.c_str());
            	}
            	else
            	{
            	    m_dynamicStartVideo.store(true);
                    LOG_PrintWarn("m_usbName:%s UVCIN No Need startStream\n",m_usbName.c_str());
            	}

        	}
        	else
        	{
                errorf("dealFlg is false\n");
        	}
    	}

        if(audioParams.isMember("Format")
          && ((m_playAbility == VIDEO_AUDIO) || (m_playAbility == AUDIO_ONLY)))
        {
            //LOG_PrintInfo("UACIN:%d ---> %s\n", UACIN,  audioParams.toStyledString().c_str());
        	result = m_usbStreamCtl->setParams(m_usbName, UACIN, audioParams);
        	if(!result)
        	{
                errorf("m_usbName:%s m_usbStreamCtl->setParams UACIN failed\n",m_usbName.c_str());
                return false;
        	}

    	    AudioInAttr format = {0};
    	    format.enSampleFormat = SAMPLE_FMT_S16;               	
        	format.enAiLayout = AI_NORMAL;
        	format.source = EXTERNAL_IN_TYPE;

        	if(audioParams.isMember("Rates") && audioParams.isMember("Channels"))
        	{
            	format.u32SampleRate = std::stoi(audioParams["Rates"].asString());
            	format.u32Channels = std::stoi(audioParams["Channels"].asString());
        	}

        	//format.isNeedResampler = CurtainActManager::instance()->isAudioNeedResampler(m_streamInfo, format.u32SampleRate) ? 1 : 0; //todo
    	    
            m_pAudioInput->setFormat(format);

        	result = m_usbStreamCtl->startStream(m_usbName, UACIN, [this](void *buffer, int length){return onAudioFrame(buffer, length);});
        	if(!result)
        	{
                errorf("m_usbName:%s m_usbStreamCtl->startStream UACIN failed\n", m_usbName.c_str());
                return false;
        	}

        	LOG_PrintInfo("m_usbName:%s UACIN startStream format.u32SampleRate=%d,format.u32Channels=%d\n",m_usbName.c_str(),format.u32SampleRate, format.u32Channels);
    	}
	}


    if(m_taskInfo.StopTime != -1)
    {
        m_taskTimer.reset(new Fdt::Timer(m_taskInfo.StopTime * 1000, ([this](){return this->stop(true);}), nullptr)); //不是循环播放，注册停止函数
    }
    else
    {
        m_taskTimer.reset();
    }

    return true;
}

	
bool UsbInStream::streamStop(void)
{
    if(((m_usbInAbility & UVCIN) == UVCIN)
      && ((m_playAbility == VIDEO_AUDIO) || (m_playAbility == VIDEO_ONLY)))
    {
         m_usbStreamCtl->stopStream(m_usbName, UVCIN);

         LOG_PrintWarn("m_usbName:%s stopStream UVCIN\n", m_usbName.c_str());
    }

    if(((m_usbInAbility & UACIN) == UACIN)
      && ((m_playAbility == VIDEO_AUDIO) || (m_playAbility == AUDIO_ONLY)))
    {
         m_usbStreamCtl->stopStream(m_usbName, UACIN);

         LOG_PrintWarn("m_usbName:%s stopStream UACIN\n", m_usbName.c_str());
    }
    
    return true;
}


bool UsbInStream::sendVideoPacket(unsigned char *buffer, int buflen, uint64_t timestamp)
{
    if(m_pVideoDecode)
    {
        m_videoPacket.buffer = buffer;
        m_videoPacket.length = buflen;
        m_videoPacket.pts = timestamp;

        //LOG_PrintWarn("sendVideoPacket CALL");

        return m_pVideoDecode->putPacket(&m_videoPacket);
    }
    return false;
}

bool UsbInStream::sendAudioPacket(unsigned char *buffer, int buflen, uint64_t timestamp)
{
    if(m_pAudioInput)
    {
        m_audioPacket.buffer = buffer;
        m_audioPacket.length = buflen;
        m_audioPacket.pts = timestamp;

        return m_pAudioInput->putPacket(&m_audioPacket);
    }

    return false;
}

bool UsbInStream::getOutputInfo(StreamOutInterface type, std::string usbPort, int *sampleRate, int *channels)
{    
    if(!m_usbStreamCtl)
    {
        return false;
    }

    Json::Value params = Json::Value::null;
    if(!getUsbAudioParams(usbPort, UACOUT, params)) 
    {
        LOG_PrintInfo("getUsbAudioParams failed\n");
        return false;
    }

	//LOG_PrintInfo("UACOUT:%d ---> %s\n", UACOUT,  params.toStyledString().c_str());

	*sampleRate = std::stoi(params["Rates"].asString());
	
    *channels = std::stoi(params["Channels"].asString());

    return true;
	
}

bool UsbInStream::outputStart(StreamOutInterface type, std::string usbPort)
{
    if(!m_usbStreamCtl)
    {
        return false;
    }

	m_usbOutPort = usbPort;
    m_outType = type;

    m_outEnable = true;

	Json::Value params = Json::Value::null;
	if(getUsbAudioParams(usbPort, UACOUT, params))
	{
        //LOG_PrintInfo("setParams---> %s\n", params.toStyledString().c_str());    	
        bool result = m_usbStreamCtl->setParams(usbPort, UACOUT, params);
        if (!result)
        {
            LOG_PrintInfo("UACOUT setParams error\n");
            return false;
        }
        m_uacOutParams = params; //uacout参数更新
    }
    else 
    {
        LOG_PrintInfo("getUsbAudioParams failed\n");
        return false;
    }

    m_outRates = std::stoi(params["Rates"].asString());
    
    AudioEncFormat encFormat;
    memset(&encFormat, 0, sizeof(encFormat));
	encFormat.type = audioEncPCM;
    encFormat.pack = audioEncPackTypeRAW;
    encFormat.frequency = m_outRates;
    encFormat.channelNum = std::stoi(params["Channels"].asString());
    encFormat.depth = 16;
    AudioEncode::instance(m_outType)->setFormat(&encFormat);

	AudioEncode::instance(m_outType)->start();

	m_thread.start([this](Fdt::Thread *thread){this->ThreadProc(thread);}); //启动单独线程处理流

	return true;
}

bool UsbInStream::outputStop(StreamOutInterface type, std::string usbPort, bool flag)
{
    if((m_outType == type) && (m_usbOutPort == usbPort) && m_outEnable)
    {
		m_thread.stop();

        if(flag) //falg为false代表本地热插拔暂时停止，为true代表远端控制停止
        {
            m_outEnable = false;

            m_usbStreamCtl->stopStream(usbPort, UACOUT);
        }
                
        AudioEncode::instance(m_outType)->stop();         
    }

    return true;
}

void UsbInStream::ThreadProc(Fdt::Thread *thread)
{
    thread->setPriority(Fdt::PRIORITY_NORMAL, Fdt::POLICY_RR);

    char data[MAX_PCM_SIZE] = {0};
    int dataLen = 0;
    bool iRet = false;
    int sampleLen = m_outRates / 1000 * AUDIO_ALG_TIME;

    uint64_t runtime = 0;
    
    while (1)
    {
        if(!m_outEnable)
        {
            thread->sleep(50);
            continue;
        } 
        
        ///getdata
        memset(data, 0, sizeof(data));
        dataLen = 0;
        
        iRet = AudioEncode::instance(m_outType)->getPacket(data, &dataLen);
        if(iRet && (dataLen > 0))
        {
            //media_FILE_Write("/nfsroot/wyg/UACOUT.pcm", data, dataLen);

            //audioVolumeConvert((short*)data, dataLen); //音量控制
        
            iRet = m_usbStreamCtl->writeStream(m_usbOutPort, UACOUT, data, sampleLen); //sampleLen底层每次写入alsa使用，实际总共写入dataLen
            if(iRet == false)
            {
                LOG_PrintWarn("writeStream failed, dataLen:%d\n",sampleLen);
            }  
            
            thread->sleep(3);
        }

        thread->sleep(1);
    }

    return;
}

bool UsbInStream::volumeFactorSet(int value)
{
    m_volumeFactor = value;//todo

    LOG_PrintWarn("volumeFactorSet m_volumeFactor:%d\n",m_volumeFactor);
    return true;
}
 
bool UsbInStream::audioVolumeConvert(short* audioData, int dataLen)
{
    if(!audioData || dataLen <= 0)
    {
        return false;
    }
    
    for(int i = 0; i < dataLen / 2; ++i)
    {        
        audioData[i] = audioData[i] * m_volumeFactor / 100;
    }

    return true;
}

bool UsbInStream::getUsbDevAbility(int& ability)
{
    ability = m_usbInAbility;

    return true;
}

bool UsbInStream::isH26xFormat()
{
    if(m_usbInFormat == "H.264" || m_usbInFormat == "H.265")
    {
        return true;
    }
    
    return false;
}

bool UsbInStream::dynamicStartVideo(bool actFlg)
{
    if(actFlg && m_dynamicStartVideo.load())
    {
        m_dropFrame = true;
        bool result = m_usbStreamCtl->startStream(m_usbName, UVCIN, [this](void *buffer, int length){return onVideoFrame(buffer, length);});
        if(!result)
    	{
            errorf("m_usbName:%s m_usbStreamCtl->setParams UVCIN failed\n", m_usbName.c_str());
            return false;
    	}
    	m_dynamicStartVideo.store(false);   	

    	LOG_PrintInfo("m_usbName:%s UVCIN startStream success\n",m_usbName.c_str());
    }
    else if(!actFlg && !m_dynamicStartVideo.load())
    {
        if(((m_usbInAbility & UVCIN) == UVCIN)
          && ((m_playAbility == VIDEO_AUDIO) || (m_playAbility == VIDEO_ONLY)))
        {
             m_usbStreamCtl->stopStream(m_usbName, UVCIN);

             clearVideoQueue(0);
             clearVideoQueue(1);

             m_dynamicStartVideo.store(true);  

             LOG_PrintInfo("m_usbName:%s stopStream UVCIN\n", m_usbName.c_str());
        }
    }
    
    
    return true;
}

bool UsbInStream::getUsbAudioParams(string usbPort, int ability, Json::Value &outParams)
{
    Json::Value params = Json::Value::null;
	m_usbStreamCtl->getSupportParams(usbPort, ability, params);	
	if((!params.isMember("Format")) 
	    || (!params.isMember("Channels"))
	    || (!params.isMember("Rates")))
	{
	    LOG_PrintInfo("UAC Params error\n");
        return false;
	}

	LOG_PrintInfo("ability:%d,usbPort:%s ---> %s\n", ability, usbPort.c_str(), params.toStyledString().c_str());


    std::string rateList = params["Rates"].asString();
    uint8_t len = sizeof(audioRates) / sizeof(std::string);
    uint8_t i = 0;
    for( ; i < len; ++i)
    {
	    if(rateList.find(audioRates[i]) != std::string::npos)
	    {
            params["Rates"] = audioRates[i];
            break;
	    }
	}
	if(i == len)
	{
        LOG_PrintInfo("UAC Rates unsupport\n");
        return false;
    }

    outParams = params;

    return true;
}



}



